package com.hoshiicloud.as2c.minipro.controller;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.hoshiicloud.common.controller.BaseController;
import com.hoshiicloud.common.exception.ServiceException;
import com.hoshiicloud.common.rpc.Response;
import com.hoshiicloud.common.utils.SMSCodeUtil;
import com.hoshiicloud.as2c.minipro.dto.WeChatSession;
import com.hoshiicloud.as2c.minipro.feign.VeriCenterFeignService;
import com.hoshiicloud.as2c.minipro.param.CodeLoginParam;
import com.hoshiicloud.as2c.minipro.param.WXLoginParam;
import com.hoshiicloud.as2c.minipro.service.ILoginService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;

/**
 * C端用户登录相关操作Controller类
 *
 * @author : yangcheng
 * @date : 2019/5/13 19:16
 * @mail : maiboyc@163.com
 **/
@Slf4j
@RestController
@RequestMapping("/login")
@Api(value = "登录管理", tags = {"登录相关操作接口"}, produces = MediaType.APPLICATION_JSON_VALUE)
public class LoginController extends BaseController {

    // 小程序APPID
    @Value("${weChat.app-id}")
    @Autowired
    private String APPID;

    // 小程序SECRET
    @Value("${weChat.app-secret}")
    @Autowired
    private String SECRET;

    // 短信验证码失效时间
    @Value("${sms.expireSeconds}")
    @Autowired
    private Long expireSeconds;

    // 登录相关Service
    @Autowired
    private ILoginService loginService;

    // 验证中心微服务Service
    @Autowired
    private VeriCenterFeignService veriCenterFeignService;

    /**
     * 发送验证码
     * @param mobile 手机号码
     * @return Response
     */
    @GetMapping("/{mobile}")
    @ApiOperation(value = "发送手机验证码", notes = "根据手机号码发送验证码", consumes = MediaType.ALL_VALUE)
    public Response<String> verifCode(@PathVariable("mobile") String mobile) {
        Response<String> rs;
        try {
            // 生成手机6位验证码
            String code = SMSCodeUtil.code(4);
            Response send_rs = veriCenterFeignService.sendCode(mobile,code,expireSeconds);
            if (null != send_rs && send_rs.getCode() == 200 && null != send_rs.getData()) {
                rs = Response.data((String)send_rs.getData());
            } else {
                rs = Response.failed("短信验证码发送失败");
            }
        } catch (Exception e) {
            log.error("根据手机号码发送验证码异常"+"["+e.getMessage()+"]");
            rs = Response.failed(e.getMessage());
        }
        return rs;
    }

    /**
     * 手机号+验证码登录(手机号+验证码注册)
     * @param param     手机验证码登录参数
     * @return Response
     */
    @PostMapping("/loginByCode")
    @ApiOperation(value = "手机号+验证码登录", notes = "手机号+验证码登录", consumes = MediaType.APPLICATION_JSON_VALUE)
    public Response codeLogin(@RequestBody @Valid CodeLoginParam param, BindingResult result) {
        Response rs;
        try {
            if (CollectionUtils.isNotEmpty(handleValidMsg(result))){// 验证不通过
                rs = Response.failed(JSON.toJSONString(handleValidMsg(result)));
            } else {// 验证通过
                Response check_rs = veriCenterFeignService.checkCode(param.getMsgId(),param.getCode());
                if (null != check_rs && check_rs.getCode() == 200 && "验证成功".equals(check_rs.getMsg())) {// 验证短信验证码成功，插入会员记录
                    rs = loginService.codeLogin(param.getCompanyId(), param.getPlatformId(), param.getMobile(),param.getInvitationCode());
                } else {// 验证失败,将验证信息返回
                    rs = Response.failed("登录失败："+check_rs.getMsg());
                }
            }
        } catch (ServiceException e) {
            log.error("根据手机号码和验证码登录异常"+"["+e.getMessage()+"]");
            rs = Response.failed("登录失败："+e.getError());
        } catch (Exception e) {
            log.error("根据手机号码和验证码登录异常"+"["+e.getMessage()+"]");
            rs = Response.failed("登录失败："+"["+e.getMessage()+"]");
        }
        return rs;
    }

    /**
     * 微信登录(用户在app端点击微信登录调用微信开放平台授权登录，拿到信息以后需要存入到当前的会员信息表中)
     * @param param     微信登录参数
     * @return Response
     */
    @PostMapping("/loginByWeChat")
    @ApiOperation(value = "微信登录", notes = "使用微信登录", consumes = MediaType.APPLICATION_JSON_VALUE)
    public Response loginByWeChat(@RequestBody @Valid WXLoginParam param) {
        Response rs;
        try {
            String url = "https://api.weixin.qq.com/sns/jscode2session?appid="+APPID+"&secret="+SECRET+"&js_code="+ param.getCode() +"&grant_type=authorization_code";
            RestTemplate restTemplate = new RestTemplate();
            //进行网络请求,访问url接口
            ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.GET, null, String.class);
            //根据返回值进行后续操作
            if(responseEntity != null && responseEntity.getStatusCode() == HttpStatus.OK) {
                String sessionData = responseEntity.getBody();
                //解析从微信服务器获得的openid和session_key;
                WeChatSession weChatSession = JSON.parseObject(sessionData,WeChatSession.class);
                //获取用户的唯一标识
                String openid = weChatSession.getOpenid();
                if(StringUtils.isEmpty(openid)){
                    rs = Response.failed("请求微信接口失败");
                    log.error("请求微信接口失败:"+sessionData);
                }else{
                    //获取会话秘钥
                    String session_key = weChatSession.getSession_key();
                    //最后要返回一个自定义的登录态,用来做后续数据传输的验证
                    rs = loginService.wxLogin(param.getCompanyId(),param.getPlatformId(),param.getInvitationCode(),param.getNickname(),param.getSex(),param.getProvince(),param.getCity(),param.getCountry(),param.getHeadimgurl(),session_key,openid,APPID,param.getEncryptedData(),param.getIv());
                }
            } else {
                rs = Response.failed("请求微信接口失败");
                log.error("请求微信接口失败");
            }
        } catch (Exception e) {
            log.error("微信登录出现异常"+"["+e.getMessage()+"]");
            rs = Response.failed("微信登录出现异常"+"["+e.getMessage()+"]");
        }
        return rs;
    }

    /**
     * 小程序微信已经登录过不需要再登录
     * @param param 参数{"companyId":1,"platformId":2,"code":"1345"}
     * @return
     */
    @PostMapping("/loginByWeChatResident")
    @ApiOperation(value = "微信常驻登录", notes = "使用微信常驻登录", consumes = MediaType.APPLICATION_JSON_VALUE)
    public Response<Map<String,Object>> loginByWeChatResident(@RequestBody Map<String,Object> param) {
        Response<Map<String,Object>> rs;
        try {
            String url = "https://api.weixin.qq.com/sns/jscode2session?appid="+APPID+"&secret="+SECRET+"&js_code="+ param.get("code") +"&grant_type=authorization_code";
            RestTemplate restTemplate = new RestTemplate();
            //进行网络请求,访问url接口
            ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.GET, null, String.class);
            //根据返回值进行后续操作
            if(responseEntity != null && responseEntity.getStatusCode() == HttpStatus.OK) {
                String sessionData = responseEntity.getBody();
                //解析从微信服务器获得的openid和session_key;
                WeChatSession weChatSession = JSON.parseObject(sessionData,WeChatSession.class);
                //获取用户的唯一标识
                String openid = weChatSession.getOpenid();
                //获取会话秘钥
                String session_key = weChatSession.getSession_key();
                if (StringUtils.isNotEmpty(openid)) {
                    Map<String,Object> map = new HashMap<>();
                    map.put("companyId",param.get("companyId"));
                    map.put("platformId",param.get("platformId"));
                    map.put("openId",openid);
                    Response<Map<String,Object>> info_rs = loginService.getMemberWithConsumerInfo(map);
                    if (null == info_rs.getData()) {
                        rs = Response.failed("当前微信没有注册过，请重新注册登录");
                    } else {
                        rs = info_rs;
                    }
                } else {
                    rs = Response.failed(responseEntity.getBody());
                }
            } else {
                rs = Response.failed("请求微信接口失败");
            }
        } catch (Exception e) {
            log.error("微信登录出现异常"+"["+e.getMessage()+"]");
            rs = Response.failed();
        }
        return rs;
    }
}